package utils

import (
	"bytes"
	"context"
	"crypto/md5"
	"crypto/tls"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"io"
	"log"
	"net/http"
	neturl "net/url"
	"os"
	"strings"
	"time"

	"github.com/mark3labs/mcp-go/mcp"
	"github.com/mark3labs/mcp-go/server"
)

// Tool name length constraints
const (
	MaxToolNameLength = 60 // Maximum allowed tool name length
	HashSuffixLength  = 8  // Length of hash suffix for uniqueness
	MinPrefixLength   = 8  // Minimum length for mcplink prefix
	MinMethodLength   = 3  // Minimum length for HTTP method (get/put)
	MinPathLength     = 5  // Minimum meaningful path length
)

// constructURL properly constructs a URL from baseURL and path
// ensuring correct slash handling
func constructURL(baseURL, path string) string {
	// Remove trailing slash from baseURL if present
	baseURL = strings.TrimSuffix(baseURL, "/")

	// Ensure path starts with a slash
	if !strings.HasPrefix(path, "/") {
		path = "/" + path
	}

	return baseURL + path
}

func sanitizeToolName(name string) string {
	// Convert to lowercase and replace common separators with underscore
	s := strings.ToLower(name)

	// Replace special characters
	s = strings.ReplaceAll(s, " ", "_")
	s = strings.ReplaceAll(s, "-", "_")
	s = strings.ReplaceAll(s, "/", "_")
	s = strings.ReplaceAll(s, ".", "_")
	s = strings.ReplaceAll(s, "{", "")
	s = strings.ReplaceAll(s, "}", "")
	s = strings.ReplaceAll(s, ":", "_")
	s = strings.ReplaceAll(s, "?", "")
	s = strings.ReplaceAll(s, "&", "and")
	s = strings.ReplaceAll(s, "=", "_eq_")
	s = strings.ReplaceAll(s, "%", "_pct_")

	// Remove consecutive underscores
	for strings.Contains(s, "__") {
		s = strings.ReplaceAll(s, "__", "_")
	}

	// Remove trailing underscore
	s = strings.TrimSuffix(s, "_")

	// Remove leading underscore
	s = strings.TrimPrefix(s, "_")

	// Ensure the name is not empty
	if s == "" {
		return "unnamed_tool"
	}

	return s
}

// debugParameterStructure logs detailed information about parameter structure
func debugParameterStructure(params map[string]interface{}, toolName string) {
	log.Printf("[PARAM_DEBUG] Tool: %s, Raw params structure analysis:", toolName)
	
	// Check for structured parameters
	hasPathNames := params["pathNames"] != nil
	hasSearchParams := params["searchParams"] != nil
	hasRequestBody := params["requestBody"] != nil
	
	log.Printf("[PARAM_DEBUG] - pathNames: %v", hasPathNames)
	log.Printf("[PARAM_DEBUG] - searchParams: %v", hasSearchParams)
	log.Printf("[PARAM_DEBUG] - requestBody: %v", hasRequestBody)
	
	// If no structured parameters, list all top-level parameters
	if !hasPathNames && !hasSearchParams && !hasRequestBody {
		log.Printf("[PARAM_DEBUG] - Flat parameters detected:")
		for key, value := range params {
			valueType := fmt.Sprintf("%T", value)
			log.Printf("[PARAM_DEBUG]   - %s: %s", key, valueType)
		}
		log.Printf("[PARAM_DEBUG] - This indicates a parameter mapping issue!")
		log.Printf("[PARAM_DEBUG] - Expected structure: {pathNames: {...}, searchParams: {...}, requestBody: {...}}")
	} else {
		// Log structured parameter details
		if hasRequestBody {
			if requestBodyMap, ok := params["requestBody"].(map[string]interface{}); ok {
				log.Printf("[PARAM_DEBUG] - requestBody contains %d fields:", len(requestBodyMap))
				for key := range requestBodyMap {
					log.Printf("[PARAM_DEBUG]   - %s", key)
				}
			}
		}
	}
}

// enhancedParameterMapping provides intelligent parameter mapping with fallback logic
func enhancedParameterMapping(params map[string]interface{}, url string, toolName string) (
	pathParams, queryParams, bodyParams map[string]interface{}) {
	
	pathParams = make(map[string]interface{})
	queryParams = make(map[string]interface{})
	bodyParams = make(map[string]interface{})
	
	// First, try structured parameters
	if pathParamsMap, ok := params["pathNames"].(map[string]interface{}); ok {
		pathParams = pathParamsMap
		log.Printf("[PARAM_MAPPING] Tool: %s, Found pathNames with %d parameters", toolName, len(pathParams))
	}
	
	if urlParamsMap, ok := params["searchParams"].(map[string]interface{}); ok {
		queryParams = urlParamsMap
		log.Printf("[PARAM_MAPPING] Tool: %s, Found searchParams with %d parameters", toolName, len(queryParams))
	}
	
	if requestBodyMap, ok := params["requestBody"].(map[string]interface{}); ok {
		bodyParams = requestBodyMap
		log.Printf("[PARAM_MAPPING] Tool: %s, Found requestBody with %d parameters", toolName, len(bodyParams))
	}
	
	// If no structured parameters found, use intelligent mapping
	if len(pathParams) == 0 && len(queryParams) == 0 && len(bodyParams) == 0 {
		log.Printf("[PARAM_MAPPING] Tool: %s, No structured parameters found, using intelligent mapping", toolName)
		bodyParams = smartParameterMapping(params, url, toolName)
	}
	
	return pathParams, queryParams, bodyParams
}

// smartParameterMapping intelligently maps flat parameters
func smartParameterMapping(params map[string]interface{}, url string, toolName string) map[string]interface{} {
	bodyParams := make(map[string]interface{})
	
	for paramName, paramValue := range params {
		// Skip system parameters
		if isSystemParameter(paramName) {
			log.Printf("[PARAM_MAPPING] Tool: %s, Skipping system parameter: %s", toolName, paramName)
			continue
		}
		
		// Check if it's a path parameter
		placeholder := fmt.Sprintf("{%s}", paramName)
		if strings.Contains(url, placeholder) {
			log.Printf("[PARAM_MAPPING] Tool: %s, Parameter %s is a path parameter, skipping from body", toolName, paramName)
			continue
		}
		
		// Add to body parameters
		bodyParams[paramName] = paramValue
		log.Printf("[PARAM_MAPPING] Tool: %s, Added parameter %s to requestBody", toolName, paramName)
	}
	
	log.Printf("[PARAM_MAPPING] Tool: %s, Final requestBody contains %d parameters", toolName, len(bodyParams))
	return bodyParams
}

// isSystemParameter checks if a parameter name is a system parameter
func isSystemParameter(paramName string) bool {
	systemParams := []string{"pathNames", "searchParams", "requestBody"}
	for _, sysParam := range systemParams {
		if paramName == sysParam {
			return true
		}
	}
	return false
}

// generateShortHash creates a short hash from input string for uniqueness
func generateShortHash(input string) string {
	hash := md5.Sum([]byte(input))
	return hex.EncodeToString(hash[:])[:HashSuffixLength]
}

// smartTruncateToolName intelligently truncates tool name while preserving key information
func smartTruncateToolName(prefix, method, path string) string {
	// Calculate available space for components
	availableLength := MaxToolNameLength

	// Reserve space for underscores between components (2 underscores)
	availableLength -= 2

	// Allocate space with priority: prefix > method > path
	prefixBudget := MinPrefixLength
	methodBudget := MinMethodLength
	pathBudget := availableLength - prefixBudget - methodBudget

	// Optimize prefix (remove redundant mcplink_ if too long)
	trimmedPrefix := prefix
	if len(prefix) > prefixBudget {
		// Try to extract meaningful part after mcplink_
		if strings.HasPrefix(prefix, "mcplink_") {
			core := strings.TrimPrefix(prefix, "mcplink_")
			if len(core) <= prefixBudget {
				trimmedPrefix = core
			} else {
				// Keep first part of core name
				trimmedPrefix = core[:prefixBudget]
			}
		} else {
			trimmedPrefix = prefix[:prefixBudget]
		}
	}

	// Method is usually short, just use as-is or truncate
	trimmedMethod := method
	if len(method) > methodBudget {
		trimmedMethod = method[:methodBudget]
	}

	// Intelligently truncate path - keep meaningful parts
	trimmedPath := smartTruncatePath(path, pathBudget)

	// Construct the name
	result := fmt.Sprintf("%s_%s_%s", trimmedPrefix, trimmedMethod, trimmedPath)

	// Final sanitization
	result = sanitizeToolName(result)

	// If still too long, apply hard truncation
	if len(result) > MaxToolNameLength {
		result = result[:MaxToolNameLength-1] // Leave room for potential hash suffix
	}

	return result
}

// smartTruncatePath intelligently truncates API path, keeping meaningful segments
func smartTruncatePath(path string, maxLength int) string {
	if len(path) <= maxLength {
		return path
	}

	// Split path into segments
	segments := strings.Split(strings.Trim(path, "/"), "/")
	if len(segments) == 0 {
		return "api"
	}

	// Priority: last segment (endpoint) > first segment (version/module) > middle segments
	var result []string
	currentLength := 0

	// Always try to include the last segment (endpoint name)
	if len(segments) > 0 {
		lastSegment := segments[len(segments)-1]
		if len(lastSegment) <= maxLength {
			result = []string{lastSegment}
			currentLength = len(lastSegment)
		}
	}

	// Add first segment if there's space (often version/module info)
	if len(segments) > 1 && currentLength > 0 {
		firstSegment := segments[0]
		neededLength := currentLength + 1 + len(firstSegment) // +1 for underscore
		if neededLength <= maxLength {
			result = append([]string{firstSegment}, result...)
			currentLength = neededLength
		}
	}

	// Add middle segments if there's space
	for i := 1; i < len(segments)-1 && currentLength < maxLength; i++ {
		segment := segments[i]
		neededLength := currentLength + 1 + len(segment)
		if neededLength <= maxLength {
			result = append(result[:len(result)-1], append([]string{segment}, result[len(result)-1])...)
			currentLength = neededLength
		} else {
			break
		}
	}

	if len(result) == 0 {
		// Fallback: just truncate the path
		return path[:maxLength]
	}

	truncatedPath := strings.Join(result, "_")

	// Apply final length check
	if len(truncatedPath) > maxLength {
		truncatedPath = truncatedPath[:maxLength]
	}

	return truncatedPath
}

// ensureUniqueToolName ensures tool name uniqueness by adding hash suffix if needed
func ensureUniqueToolName(baseName string, originalFullName string, existingNames map[string]bool) string {
	// Check if base name is already unique
	if !existingNames[baseName] {
		return baseName
	}

	// Generate hash from original full name for consistency
	hashSuffix := generateShortHash(originalFullName)

	// Calculate available space for hash
	availableSpace := MaxToolNameLength - HashSuffixLength - 1 // -1 for underscore

	// Truncate base name if needed to make room for hash
	truncatedBase := baseName
	if len(baseName) > availableSpace {
		truncatedBase = baseName[:availableSpace]
	}

	// Construct final name with hash
	uniqueeName := fmt.Sprintf("%s_%s", truncatedBase, hashSuffix)

	return uniqueeName
}

// extractDisplayNameFromTool extracts a friendly display name from the technical MCP tool name
func extractDisplayNameFromTool(toolName string) string {
	// Handle hash suffixed names (from uniqueness guarantee)
	if strings.Contains(toolName, "_") {
		parts := strings.Split(toolName, "_")
		// Check if last part looks like a hash (8 chars, alphanumeric)
		if len(parts) > 1 {
			lastPart := parts[len(parts)-1]
			if len(lastPart) == HashSuffixLength && isHexString(lastPart) {
				// Remove hash suffix for display
				toolName = strings.Join(parts[:len(parts)-1], "_")
			}
		}
	}

	// Remove the mcplink_ prefix if present
	if strings.HasPrefix(toolName, "mcplink_") {
		toolName = strings.TrimPrefix(toolName, "mcplink_")
	}

	// Handle common patterns like "search_get_api_houses"
	// Extract meaningful parts for better readability
	parts := strings.Split(toolName, "_")
	if len(parts) == 0 {
		return toolName
	}

	// Strategy: try to create a readable name from key parts
	var displayParts []string

	// Add the first part (usually the service/module name)
	if len(parts) > 0 && len(parts[0]) > 0 {
		displayParts = append(displayParts, parts[0])
	}

	// Skip common HTTP methods for display
	for i, part := range parts {
		lowerPart := strings.ToLower(part)
		// Skip HTTP methods
		if lowerPart == "get" || lowerPart == "post" || lowerPart == "put" || lowerPart == "delete" || lowerPart == "patch" {
			continue
		}
		// Skip common API patterns
		if lowerPart == "api" || lowerPart == "v1" || lowerPart == "v2" {
			continue
		}
		// Add meaningful endpoint names
		if i > 0 && len(part) > 2 { // Avoid very short parts
			displayParts = append(displayParts, part)
			// Limit to 3 parts for readability
			if len(displayParts) >= 3 {
				break
			}
		}
	}

	// If we have meaningful parts, join them
	if len(displayParts) > 1 {
		return strings.Join(displayParts, "")
	}

	// Fallback: return the first meaningful part or original name
	if len(displayParts) > 0 {
		return displayParts[0]
	}

	return toolName
}

// isHexString checks if a string contains only hexadecimal characters
func isHexString(s string) bool {
	for _, c := range s {
		if !((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')) {
			return false
		}
	}
	return true
}

// sensitiveFields defines patterns for sensitive information that should be masked in logs
// Updated with comprehensive coverage of sensitive data types
var sensitiveFields = []string{
	// Authentication & Authorization
	"password", "passwd", "pwd", "token", "secret", "key", "auth", "credential",
	"x-api-key", "authorization", "x-auth-token", "bearer", "access_token",
	"refresh_token", "id_token", "jwt", "session", "sessionid", "session_id",
	"csrf_token", "xsrf_token", "api_secret", "client_secret", "private_key",
	// Database & Connection strings
	"database_url", "db_url", "connection_string", "conn_str", "dsn",
	"db_password", "mysql_password", "postgres_password", "redis_password",
	// Cloud & Service credentials
	"aws_secret", "aws_access_key", "azure_key", "gcp_key", "service_account",
	"webhook_secret", "signing_secret", "encryption_key", "decrypt_key",
	// Certificates & Keys
	"cert", "certificate", "pem", "p12", "pfx", "keystore", "truststore",
	// OAuth & SAML
	"client_assertion", "saml_response", "oauth_token", "oauth_secret",
}

// maskSensitiveData masks sensitive information in the given data
func maskSensitiveData(data interface{}) interface{} {
	switch v := data.(type) {
	case map[string]interface{}:
		masked := make(map[string]interface{})
		for key, value := range v {
			lowerKey := strings.ToLower(key)
			isSensitive := false
			for _, sensitive := range sensitiveFields {
				if strings.Contains(lowerKey, sensitive) {
					isSensitive = true
					break
				}
			}
			if isSensitive {
				masked[key] = "***MASKED***"
			} else {
				masked[key] = maskSensitiveData(value)
			}
		}
		return masked
	case []interface{}:
		masked := make([]interface{}, len(v))
		for i, item := range v {
			masked[i] = maskSensitiveData(item)
		}
		return masked
	default:
		return v
	}
}

// maskSensitiveHeaders masks sensitive headers for logging
func maskSensitiveHeaders(headers map[string]string) map[string]string {
	masked := make(map[string]string)
	for key, value := range headers {
		lowerKey := strings.ToLower(key)
		isSensitive := false
		for _, sensitive := range sensitiveFields {
			if strings.Contains(lowerKey, sensitive) {
				isSensitive = true
				break
			}
		}
		if isSensitive {
			masked[key] = "***MASKED***"
		} else {
			masked[key] = value
		}
	}
	return masked
}

// NewToolHandler creates a tool handler with static authentication (backward compatibility)
func NewToolHandler(method string, url string, extraHeaders map[string]string) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
	return NewToolHandlerWithSession(method, url, extraHeaders, nil, nil)
}

// NewToolHandlerWithParser creates a tool handler with parser support for TLS configuration
func NewToolHandlerWithParser(method string, url string, extraHeaders map[string]string, parser OpenAPIParser) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
	return NewToolHandlerWithSessionAndParser(method, url, extraHeaders, nil, nil, parser)
}

// NewToolHandlerWithSession creates a tool handler with optional session and authentication configuration
func NewToolHandlerWithSession(method string, url string, extraHeaders map[string]string, session *sseSession, authConfig *AuthConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
	return NewToolHandlerWithSessionAndParser(method, url, extraHeaders, session, authConfig, nil)
}

// NewToolHandlerWithSessionAndParser creates a tool handler with optional session, authentication configuration, and parser for TLS settings
func NewToolHandlerWithSessionAndParser(method string, url string, extraHeaders map[string]string, session *sseSession, authConfig *AuthConfig, parser OpenAPIParser) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
	return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
		// Start timing for performance monitoring
		startTime := time.Now()
		toolName := request.Params.Name

		// Extract friendly display name from tool name for better log readability
		displayName := extractDisplayNameFromTool(toolName)

		log.Printf("[API CALL START] Tool: %s (%s), Method: %s, Base URL: %s", toolName, displayName, method, url)

		// Store log entry with both technical name and display name
		globalLogStore.AddEntry(LogEntry{
			Timestamp: startTime,
			Level:     "INFO",
			ToolName:  toolName, // 使用技术名称而不是显示名称，以匹配前端查询
			Message:   fmt.Sprintf("API call started: %s %s", method, url),
			Category:  "API_CALL_START",
			Method:    method,
			URL:       url,
			Details:   fmt.Sprintf("Technical name: %s, Display name: %s", toolName, displayName),
		})
		// Extract parameters from the request
		params := request.Params.Arguments

		// Debug parameter structure
		debugParameterStructure(params, toolName)

		// 添加参数验证逻辑
		if err := validateParametersWithOpenAPI(toolName, params); err != nil {
			log.Printf("[PARAMETER_VALIDATION] Tool: %s, Validation failed: %v", toolName, err)
			globalLogStore.AddEntry(LogEntry{
				Timestamp: time.Now(),
				Level:     "WARNING",
				ToolName:  toolName,
				Message:   fmt.Sprintf("Parameter validation failed: %v", err),
				Category:  "PARAMETER_VALIDATION_ERROR",
				Details:   fmt.Sprintf("Expected vs Actual parameters mismatch"),
			})
			// 继续执行，但记录警告
		}

		// Log masked request parameters
		maskedParams := maskSensitiveData(params)
		paramsJSON, _ := json.MarshalIndent(maskedParams, "", "  ")
		log.Printf("[API CALL PARAMS] Tool: %s, Parameters: %s", toolName, string(paramsJSON))

		// Store log entry for parameters
		globalLogStore.AddEntry(LogEntry{
			Timestamp: time.Now(),
			Level:     "DEBUG",
			ToolName:  toolName, // 使用技术名称而不是显示名称
			Message:   "Request parameters",
			Category:  "API_CALL_PARAMS",
			Details:   string(paramsJSON),
		})

		// Use enhanced parameter mapping
		pathParams, queryParams, bodyParams := enhancedParameterMapping(params, url, toolName)

		// Create a copy of the URL for path parameter substitution
		finalURL := url

		// Process URL path parameters - replace {param_name} with the value from pathParams
		for paramName, paramValue := range pathParams {
			placeholder := fmt.Sprintf("{%s}", paramName)
			if strings.Contains(finalURL, placeholder) {
				// Convert the param value to string
				var strValue string
				switch v := paramValue.(type) {
				case string:
					strValue = v
				case nil:
					// Use empty string for nil path parameters
					strValue = ""
				default:
					// Convert other types to string
					strValue = fmt.Sprintf("%v", v)
				}

				// Replace the placeholder in the URL
				finalURL = strings.ReplaceAll(finalURL, placeholder, strValue)
			}
		}
		// Add query parameters to the URL
		if len(queryParams) > 0 {
			// Parse the URL to add query parameters properly
			parsedURL, err := neturl.Parse(finalURL)
			if err != nil {
				return mcp.NewToolResultText(fmt.Sprintf("Error parsing URL: %v", err)), nil
			}

			// Get existing query values or create new ones
			q := parsedURL.Query()

			// Add all query parameters
			for paramName, paramValue := range queryParams {
				// Convert the param value to string
				var strValue string
				switch v := paramValue.(type) {
				case string:
					strValue = v
				case nil:
					continue
				default:
					// Convert other types to string
					strValue = fmt.Sprintf("%v", v)
				}

				q.Add(paramName, strValue)
			}

			// Set the updated query string back to the URL
			parsedURL.RawQuery = q.Encode()
			finalURL = parsedURL.String()
		}

		// Convert body parameters to JSON for the HTTP request body
		var reqBody io.Reader = nil
		if len(bodyParams) > 0 {
			jsonParams, err := json.Marshal(bodyParams)
			if err != nil {
				return mcp.NewToolResultText(fmt.Sprintf("Error marshaling body parameters: %v", err)), nil
			}
			reqBody = bytes.NewBuffer(jsonParams)
		}

		// Log the final URL being called
		log.Printf("[API CALL URL] Tool: %s, Final URL: %s", toolName, finalURL)

		// Store log entry for final URL
		globalLogStore.AddEntry(LogEntry{
			Timestamp: time.Now(),
			Level:     "INFO",
			ToolName:  toolName, // 使用技术名称而不是显示名称
			Message:   "Final request URL",
			Category:  "API_CALL_URL",
			URL:       finalURL,
		})

		// Create HTTP request with the processed URL
		req, err := http.NewRequestWithContext(ctx, method, finalURL, reqBody)
		if err != nil {
			log.Printf("[API CALL ERROR] Tool: %s, Error creating request: %v", toolName, err)

			// Store error log entry
			globalLogStore.AddEntry(LogEntry{
				Timestamp: time.Now(),
				Level:     "ERROR",
				ToolName:  toolName, // 使用技术名称而不是显示名称
				Message:   "Error creating HTTP request",
				Category:  "API_CALL_ERROR",
				Details:   err.Error(),
				URL:       finalURL,
				Method:    method,
			})

			return mcp.NewToolResultText(fmt.Sprintf("Error creating request: %v", err)), nil
		}

		// Set headers
		if reqBody != nil {
			req.Header.Set("Content-Type", "application/json")
		}
		for key, value := range extraHeaders {
			req.Header.Set(key, value)
		}

		// Handle authentication headers if provided (static authentication)
		if authHeaders, ok := params["authHeaders"].(map[string]interface{}); ok {
			for key, value := range authHeaders {
				if strValue, ok := value.(string); ok {
					req.Header.Set(key, strValue)
				}
			}
		}

		// Apply dynamic authentication if configured and session is available
		if session != nil && authConfig != nil && len(authConfig.Requires) > 0 {
			authStates := session.authManager.GetAllAuthStates()
			if err := session.headerInjector.InjectAuthHeaders(req, authStates, authConfig); err != nil {
				log.Printf("[ERROR] Failed to inject authentication headers for tool %s: %v", toolName, err)
				globalLogStore.AddEntry(LogEntry{
					Timestamp: time.Now(),
					Level:     "ERROR",
					ToolName:  toolName,
					Message:   "Failed to inject authentication headers",
					Category:  "AUTH_ERROR",
					Details:   err.Error(),
				})
				return mcp.NewToolResultText(fmt.Sprintf("Authentication failed: %v", err)), nil
			}
		}

		// Log masked headers
		maskedHeaders := maskSensitiveHeaders(extraHeaders)
		headersJSON, _ := json.Marshal(maskedHeaders)
		log.Printf("[API CALL HEADERS] Tool: %s, Headers: %s", toolName, string(headersJSON))

		// Store log entry for headers
		globalLogStore.AddEntry(LogEntry{
			Timestamp: time.Now(),
			Level:     "DEBUG",
			ToolName:  toolName, // 使用技术名称而不是显示名称
			Message:   "Request headers",
			Category:  "API_CALL_HEADERS",
			Details:   string(headersJSON),
		})

		// Execute the request
		client := &http.Client{}
		
		// Configure TLS settings if parser is available and TLS skip verify is enabled
		if parser != nil && parser.GetTLSSkipVerify() {
			log.Printf("[TLS CONFIG] Tool: %s, TLS certificate verification disabled", toolName)
			globalLogStore.AddEntry(LogEntry{
				Timestamp: time.Now(),
				Level:     "WARNING",
				ToolName:  toolName,
				Message:   "TLS certificate verification disabled",
				Category:  "TLS_CONFIG",
				Details:   "x-mcp-tls-skip-verify is set to true",
			})
			
			transport := &http.Transport{
				TLSClientConfig: &tls.Config{
					InsecureSkipVerify: true,
				},
			}
			client.Transport = transport
		}
		
		log.Printf("[API CALL EXECUTING] Tool: %s, Sending HTTP request...", toolName)

		resp, err := client.Do(req)
		if err != nil {
			duration := time.Since(startTime)
			log.Printf("[API CALL ERROR] Tool: %s, Error executing request: %v, Duration: %v", toolName, err, duration)

			// Store error log entry
			globalLogStore.AddEntry(LogEntry{
				Timestamp: time.Now(),
				Level:     "ERROR",
				ToolName:  toolName, // 使用技术名称而不是显示名称
				Message:   "Error executing HTTP request",
				Category:  "API_CALL_ERROR",
				Details:   err.Error(),
				Duration:  duration.String(),
				URL:       finalURL,
				Method:    method,
			})

			return mcp.NewToolResultText(fmt.Sprintf("Error executing request: %v", err)), nil
		}
		defer resp.Body.Close()

		// Log response status and timing
		duration := time.Since(startTime)
		log.Printf("[API CALL RESPONSE] Tool: %s, Status: %d %s, Duration: %v", toolName, resp.StatusCode, resp.Status, duration)

		// Store response log entry
		globalLogStore.AddEntry(LogEntry{
			Timestamp:  time.Now(),
			Level:      "INFO",
			ToolName:   toolName, // 使用技术名称而不是显示名称
			Message:    fmt.Sprintf("HTTP response received: %d %s", resp.StatusCode, resp.Status),
			Category:   "API_CALL_RESPONSE",
			Duration:   duration.String(),
			StatusCode: resp.StatusCode,
			URL:        finalURL,
			Method:     method,
		})

		// Read response body
		body, err := io.ReadAll(resp.Body)
		if err != nil {
			log.Printf("[API CALL ERROR] Tool: %s, Error reading response body: %v", toolName, err)

			// Store error log entry
			globalLogStore.AddEntry(LogEntry{
				Timestamp:  time.Now(),
				Level:      "ERROR",
				ToolName:   toolName, // 使用技术名称而不是显示名称
				Message:    "Error reading response body",
				Category:   "API_CALL_ERROR",
				Details:    err.Error(),
				StatusCode: resp.StatusCode,
				URL:        finalURL,
				Method:     method,
			})

			return mcp.NewToolResultText(fmt.Sprintf("Error reading response: %v", err)), nil
		}

		// Handle login endpoints - extract tokens from successful responses
		log.Printf("[DEBUG] Token extraction check - session: %v, authConfig: %v, authType: %s, statusCode: %d", 
			session != nil, authConfig != nil, 
			func() string { if authConfig != nil { return authConfig.Type } else { return "nil" } }(), 
			resp.StatusCode)
		
		if session != nil && authConfig != nil && authConfig.Type == "login" && resp.StatusCode >= 200 && resp.StatusCode < 300 {
			if authState, err := session.tokenExtractor.ExtractToken(body, authConfig); err != nil {
				log.Printf("[WARNING] Failed to extract token from login response for tool %s: %v", toolName, err)
				globalLogStore.AddEntry(LogEntry{
					Timestamp: time.Now(),
					Level:     "WARN",
					ToolName:  toolName,
					Message:   "Failed to extract token from login response",
					Category:  "AUTH_WARNING",
					Details:   err.Error(),
				})
			} else {
				// Determine auth type from metadata or use default
				authType := "default"
				if authConfig.Metadata != nil && authConfig.Metadata["auth_type"] != "" {
					authType = authConfig.Metadata["auth_type"]
				}
				
				if err := session.authManager.SetAuthState(authType, authState); err != nil {
					log.Printf("[ERROR] Failed to store authentication state for tool %s: %v", toolName, err)
					globalLogStore.AddEntry(LogEntry{
						Timestamp: time.Now(),
						Level:     "ERROR",
						ToolName:  toolName,
						Message:   "Failed to store authentication state",
						Category:  "AUTH_ERROR",
						Details:   err.Error(),
					})
				} else {
					log.Printf("[AUTH] Successfully extracted and stored token for auth type: %s (tool: %s)", authType, toolName)
					globalLogStore.AddEntry(LogEntry{
						Timestamp: time.Now(),
						Level:     "INFO",
						ToolName:  toolName,
						Message:   fmt.Sprintf("Successfully authenticated with auth type: %s", authType),
						Category:  "AUTH_SUCCESS",
					})
				}
			}
		}

		// Log response details
		contentType := resp.Header.Get("Content-Type")
		responseLength := len(body)
		log.Printf("[API CALL RESPONSE BODY] Tool: %s, Content-Type: %s, Body Length: %d bytes", toolName, contentType, responseLength)

		// Log response body (truncated if too long)
		responsePreview := string(body)
		if len(responsePreview) > 500 {
			responsePreview = responsePreview[:500] + "...[TRUNCATED]"
		}
		log.Printf("[API CALL RESPONSE PREVIEW] Tool: %s, Body Preview: %s", toolName, responsePreview)

		// Store response body log entry
		level := "INFO"
		if resp.StatusCode >= 400 {
			level = "ERROR"
		}

		globalLogStore.AddEntry(LogEntry{
			Timestamp:  time.Now(),
			Level:      level,
			ToolName:   toolName, // 使用技术名称而不是显示名称
			Message:    fmt.Sprintf("Response body (%s, %d bytes)", contentType, responseLength),
			Category:   "API_CALL_RESPONSE_BODY",
			Details:    responsePreview,
			StatusCode: resp.StatusCode,
			URL:        finalURL,
			Method:     method,
		})

		// Log error responses in detail
		if resp.StatusCode >= 400 {
			log.Printf("[API CALL ERROR RESPONSE] Tool: %s, Status: %d, Full Body: %s", toolName, resp.StatusCode, string(body))

			// Store detailed error response
			globalLogStore.AddEntry(LogEntry{
				Timestamp:  time.Now(),
				Level:      "ERROR",
				ToolName:   toolName, // 使用技术名称而不是显示名称
				Message:    fmt.Sprintf("Error response: %d %s", resp.StatusCode, resp.Status),
				Category:   "API_CALL_ERROR_RESPONSE",
				Details:    string(body),
				StatusCode: resp.StatusCode,
				URL:        finalURL,
				Method:     method,
			})
		}

		// TODO: handle image response
		// if strings.HasPrefix(resp.Header.Get("Content-Type"), "image/") {
		// return mcp.NewToolResultImage("", base64.StdEncoding.EncodeToString(body), resp.Header.Get("Content-Type")), nil
		// }

		log.Printf("[API CALL COMPLETE] Tool: %s, Total Duration: %v, Success: %t", toolName, time.Since(startTime), resp.StatusCode < 400)

		// Store completion log entry
		totalDuration := time.Since(startTime)
		globalLogStore.AddEntry(LogEntry{
			Timestamp:  time.Now(),
			Level:      "INFO",
			ToolName:   toolName, // 使用技术名称而不是显示名称
			Message:    fmt.Sprintf("API call completed (Duration: %v, Success: %t)", totalDuration, resp.StatusCode < 400),
			Category:   "API_CALL_COMPLETE",
			Duration:   totalDuration.String(),
			StatusCode: resp.StatusCode,
			URL:        finalURL,
			Method:     method,
		})

		return mcp.NewToolResultText(string(body)), nil
	}
}



// NewMCPFromCustomParser creates an MCP server from our custom OpenAPIParser
func NewMCPFromCustomParser(baseURL string, extraHeaders map[string]string, parser OpenAPIParser, toolID string) (*server.MCPServer, error) {
	// Create a new MCP server
	apiInfo := parser.Info()
	prefix := "mcplink_" + sanitizeToolName(apiInfo.Title)

	// Use the provided tool ID if available, otherwise generate a consistent tool ID from the API info
	var finalToolID string
	if toolID != "" {
		finalToolID = toolID
		log.Printf("[TOOL MAPPING] Using provided tool ID: %s for API: %s", finalToolID, apiInfo.Title)
	} else {
		// Generate a consistent tool ID from the API info
		finalToolID = generateToolID(apiInfo)
		log.Printf("[TOOL MAPPING] Generated tool ID: %s for API: %s", finalToolID, apiInfo.Title)
	}

	s := server.NewMCPServer(
		prefix,
		apiInfo.Version,
		server.WithResourceCapabilities(true, true),
		server.WithLogging(),
	)

	// Track existing tool names for uniqueness
	existingNames := make(map[string]bool)

	// Create a mapping manager to persist MCP name mappings
	managementAPIURL := os.Getenv("MANAGEMENT_API_HOST_URL")
	if managementAPIURL == "" {
		// 使用容器间通信地址，而不是localhost
		managementAPIURL = "http://management-api:8000"
	}
	toolMappingManager := NewToolMappingManager(managementAPIURL)

	// Load existing mappings from the database
	existingMappings, err := toolMappingManager.LoadMCPNames(finalToolID)
	if err != nil {
		log.Printf("[WARNING] Failed to load existing MCP name mappings: %v", err)
		existingMappings = make(MCPNameMapping)
	}

	// Mark existing mappings as used
	for _, techName := range existingMappings {
		existingNames[techName] = true
	}

	// Create a new mapping for this session
	newMappings := make(MCPNameMapping)

	// Add all API endpoints as tools
	for _, api := range parser.APIs() {
		// Generate original full name for hash consistency
		originalFullName := fmt.Sprintf("%s_%s_%s", prefix, strings.ToLower(api.Method), api.Path)

		// Apply smart truncation
		smartName := smartTruncateToolName(prefix, strings.ToLower(api.Method), api.Path)

		// Ensure uniqueness
		finalName := ensureUniqueToolName(smartName, originalFullName, existingNames)

		// Mark name as used
		existingNames[finalName] = true

		// Log the name generation for debugging
		log.Printf("[TOOL NAME] Original: %s (len:%d) -> Smart: %s (len:%d) -> Final: %s (len:%d)",
			originalFullName, len(originalFullName),
			smartName, len(smartName),
			finalName, len(finalName))

		// Store this mapping for persistence
		endpointKey := GenerateEndpointKey(api.Method, api.Path)
		newMappings[endpointKey] = finalName

		// Parse authentication configuration from OpenAPI extensions
		var authConfig *AuthConfig
		if api.Extensions != nil {
			if authExtension, exists := api.Extensions["x-mcp-auth"]; exists {
				if parsedConfig, err := parseAuthConfigFromExtension(authExtension); err != nil {
					log.Printf("[WARNING] Failed to parse auth config for %s %s: %v", api.Method, api.Path, err)
				} else {
					authConfig = parsedConfig
					log.Printf("[AUTH CONFIG] Parsed authentication config for %s %s: type=%s, requires=%v", 
						api.Method, api.Path, authConfig.Type, authConfig.Requires)
				}
			}
		}

		// Generate enhanced tool description with authentication information and dependencies
		description := generateEnhancedToolDescription(api, authConfig)
		
		// 添加参数名称提示，避免AI使用错误的字段名
		if api.RequestBody != nil && len(api.RequestBody.Content) > 0 {
			for _, mediaType := range api.RequestBody.Content {
				if mediaType.Schema != nil && len(mediaType.Schema.Properties) > 0 {
					description += "\n\n🔧 IMPORTANT PARAMETER NAMES:"
					for propName := range mediaType.Schema.Properties {
						description += fmt.Sprintf("\n- Use '%s' (NOT '%s' or other variations)", propName, getCommonAlternative(propName))
					}
				}
			}
		}
		
		// Add dependency information for tools that require authentication
		if authConfig != nil && len(authConfig.Requires) > 0 {
			dependencyInfo := generateDependencyDescription(parser.APIs(), authConfig.Requires)
			if dependencyInfo != "" {
				description += " " + dependencyInfo
			}
		}
		
		opts := []mcp.ToolOption{
			mcp.WithDescription(description),
		}

		// Check if this endpoint requires authentication (static or dynamic)
		requiresStaticAuth := len(api.Security) > 0 && !(len(api.Security) == 1 && len(api.Security[0]) == 0)

		// Add authentication parameters for static authentication
		if requiresStaticAuth && authConfig == nil {
			opts = append(opts, mcp.WithObject("authHeaders",
				mcp.Description("Authentication headers for API calls"),
				mcp.Properties(map[string]interface{}{
					"Authorization": map[string]interface{}{
						"type":        "string",
						"description": "Bearer token for authentication",
					},
				})))
		}

		// Add parameters
		// paramsOpts := mcp.WithObject("searchParams", mcp.Description("url parameters for the tool"))
		query_props := map[string]interface{}{}
		path_props := map[string]interface{}{}

		for _, param := range api.Parameters {
			if param.In == "query" {
				query_props[param.Name] = param
				query_props["type"] = param.Schema.Type
				if param.Schema.Enum != nil {
					query_props["enum"] = param.Schema.Enum
				}
				if param.Schema.Format != "" {
					query_props["format"] = param.Schema.Format
				}
				if param.Schema.Default != nil {
					query_props["default"] = param.Schema.Default
				}
				if param.Schema.Description != "" {
					query_props["description"] = param.Schema.Description
				}
				if param.Schema.Items != nil {
					query_props["items"] = param.Schema.Items
				}
				if param.Schema.Properties != nil {
					query_props["properties"] = param.Schema.Properties
				}
			} else if param.In == "path" {
				path_props[param.Name] = param
				path_props["type"] = param.Schema.Type
				if param.Schema.Enum != nil {
					path_props["enum"] = param.Schema.Enum
				}
				if param.Schema.Format != "" {
					path_props["format"] = param.Schema.Format
				}
				if param.Schema.Default != nil {
					path_props["default"] = param.Schema.Default
				}
				if param.Schema.Description != "" {
					path_props["description"] = param.Schema.Description
				}
				if param.Schema.Items != nil {
					path_props["items"] = param.Schema.Items
				}
			}
		}

		if len(query_props) > 0 {
			opts = append(opts, mcp.WithObject("searchParams", mcp.Description("url parameters for the tool"), mcp.Properties(query_props)))
		}
		if len(path_props) > 0 {
			opts = append(opts, mcp.WithObject("pathNames", mcp.Description("path parameters for the tool"), mcp.Properties(path_props)))
		}

		// Handle request body parameters if present
		props := map[string]interface{}{}
		if api.RequestBody != nil && len(api.RequestBody.Content) > 0 {
			for _, mediaType := range api.RequestBody.Content {
				if mediaType.Schema != nil {
					for propName, propSchema := range mediaType.Schema.Properties {
						props[propName] = propSchema
						props["type"] = propSchema.Type
						if propSchema.Enum != nil {
							props["enum"] = propSchema.Enum
						}
						if propSchema.Format != "" {
							props["format"] = propSchema.Format
						}
						if propSchema.Default != nil {
							props["default"] = propSchema.Default
						}
						if propSchema.Description != "" {
							props["description"] = propSchema.Description
						}
						if propSchema.Items != nil {
							props["items"] = propSchema.Items
						}
						if propSchema.Properties != nil {
							props["properties"] = propSchema.Properties
						}
					}
				}
			}
			opts = append(opts, mcp.WithObject("requestBody", mcp.Description("request body for the tool"), mcp.Properties(props)))
		}

		// Create the tool and handler
		tool := mcp.NewTool(finalName, opts...)

		// Properly construct the full URL with correct path handling
		fullURL := constructURL(baseURL, api.Path)

		// Merge extra headers and authentication information
		mergedHeaders := make(map[string]string)
		for k, v := range extraHeaders {
			mergedHeaders[k] = v
		}

		// Create handler with authentication configuration if available
		// Note: For the basic NewMCPFromCustomParser, we don't have a session,
		// so dynamic authentication won't work. This is for compatibility.
		// Users should use NewMCPFromCustomParserWithDynamicAuth for full dynamic auth support.
		var handler func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error)
		if authConfig != nil {
			// Log that dynamic auth config was found but session is not available
			log.Printf("[AUTH CONFIG] Dynamic auth config found for %s %s but no session available. Use NewMCPFromCustomParserWithDynamicAuth for full support.", api.Method, api.Path)
			// Fall back to static handler with parser support
			handler = NewToolHandlerWithSessionAndParser(api.Method, fullURL, mergedHeaders, nil, nil, parser)
		} else {
			// Use static authentication handler with parser support
			handler = NewToolHandlerWithSessionAndParser(api.Method, fullURL, mergedHeaders, nil, nil, parser)
		}

		// Add the tool to the server
		s.AddTool(tool, handler)
	}

	// Save all mappings to the database
	saveErr := toolMappingManager.SaveMCPNames(finalToolID, newMappings)
	if saveErr != nil {
		log.Printf("[WARNING] Failed to save MCP name mappings: %v", saveErr)
		// 我们依然继续创建MCP服务器，但不显示成功消息
	} else {
		log.Printf("[TOOL MAPPING] Successfully saved %d MCP name mappings for tool ID: %s", len(newMappings), finalToolID)
	}

	return s, nil
}

// NewMCPFromCustomParserWithDynamicAuth creates an MCP server with dynamic authentication support
func NewMCPFromCustomParserWithDynamicAuth(baseURL string, extraHeaders map[string]string, parser OpenAPIParser, toolID string, session *sseSession) (*server.MCPServer, error) {
	// Create a new MCP server
	apiInfo := parser.Info()
	prefix := "mcplink_" + sanitizeToolName(apiInfo.Title)

	// Use the provided tool ID if available, otherwise generate a consistent tool ID from the API info
	var finalToolID string
	if toolID != "" {
		finalToolID = toolID
		log.Printf("[TOOL MAPPING] Using provided tool ID: %s for API: %s", finalToolID, apiInfo.Title)
	} else {
		// Generate a consistent tool ID from the API info
		finalToolID = generateToolID(apiInfo)
		log.Printf("[TOOL MAPPING] Generated tool ID: %s for API: %s", finalToolID, apiInfo.Title)
	}

	s := server.NewMCPServer(
		prefix,
		apiInfo.Version,
		server.WithResourceCapabilities(true, true),
		server.WithLogging(),
	)

	// Track existing tool names for uniqueness
	existingNames := make(map[string]bool)

	// Create a mapping manager to persist MCP name mappings
	managementAPIURL := os.Getenv("MANAGEMENT_API_HOST_URL")
	if managementAPIURL == "" {
		managementAPIURL = "http://management-api:8000"
	}
	toolMappingManager := NewToolMappingManager(managementAPIURL)

	// Load existing mappings from the database
	existingMappings, err := toolMappingManager.LoadMCPNames(finalToolID)
	if err != nil {
		log.Printf("[WARNING] Failed to load existing MCP name mappings: %v", err)
		existingMappings = make(MCPNameMapping)
	}

	// Mark existing mappings as used
	for _, techName := range existingMappings {
		existingNames[techName] = true
	}

	// Create a new mapping for this session
	newMappings := make(MCPNameMapping)

	// Note: Auth config parsing is done directly from extensions

	// Add all API endpoints as tools
	for _, api := range parser.APIs() {
		// Generate original full name for hash consistency
		originalFullName := fmt.Sprintf("%s_%s_%s", prefix, strings.ToLower(api.Method), api.Path)

		// Apply smart truncation
		smartName := smartTruncateToolName(prefix, strings.ToLower(api.Method), api.Path)

		// Ensure uniqueness
		finalName := ensureUniqueToolName(smartName, originalFullName, existingNames)

		// Mark name as used
		existingNames[finalName] = true

		// Log the name generation for debugging
		log.Printf("[TOOL NAME] Original: %s (len:%d) -> Smart: %s (len:%d) -> Final: %s (len:%d)",
			originalFullName, len(originalFullName),
			smartName, len(smartName),
			finalName, len(finalName))

		// Store this mapping for persistence
		endpointKey := GenerateEndpointKey(api.Method, api.Path)
		newMappings[endpointKey] = finalName

		// Parse authentication configuration from OpenAPI extensions
		var authConfig *AuthConfig
		if api.Extensions != nil {
			if authExtension, exists := api.Extensions["x-mcp-auth"]; exists {
				if parsedConfig, err := parseAuthConfigFromExtension(authExtension); err != nil {
					log.Printf("[WARNING] Failed to parse auth config for %s %s: %v", api.Method, api.Path, err)
				} else {
					authConfig = parsedConfig
					// Store auth config in session for this path
					if session != nil {
						session.SetAuthConfig(api.Path, authConfig)
					}
					log.Printf("[AUTH CONFIG] Parsed and stored authentication config for %s %s: type=%s, requires=%v", 
						api.Method, api.Path, authConfig.Type, authConfig.Requires)
				}
			}
		}

		// Generate enhanced tool description with authentication information and dependencies
		description := generateEnhancedToolDescription(api, authConfig)
		
		// Add dependency information for tools that require authentication
		if authConfig != nil && len(authConfig.Requires) > 0 {
			dependencyInfo := generateDependencyDescription(parser.APIs(), authConfig.Requires)
			if dependencyInfo != "" {
				description += " " + dependencyInfo
			}
		}
		
		// Define tool options
		opts := []mcp.ToolOption{
			mcp.WithDescription(description),
		}

		// Check if this endpoint requires authentication (either static or dynamic)
		requiresStaticAuth := len(api.Security) > 0 && !(len(api.Security) == 1 && len(api.Security[0]) == 0)
		requiresDynamicAuth := authConfig != nil // Any endpoint with auth config should use dynamic auth

		// Add authentication parameters for static authentication if needed
		if requiresStaticAuth && !requiresDynamicAuth {
			opts = append(opts, mcp.WithObject("authHeaders",
				mcp.Description("Authentication headers for API calls"),
				mcp.Properties(map[string]interface{}{
					"Authorization": map[string]interface{}{
						"type":        "string",
						"description": "Bearer token for authentication",
					},
				})))
		}

		// Add parameters
		query_props := map[string]interface{}{}
		path_props := map[string]interface{}{}

		for _, param := range api.Parameters {
			if param.In == "query" {
				query_props[param.Name] = param
				query_props["type"] = param.Schema.Type
				if param.Schema.Enum != nil {
					query_props["enum"] = param.Schema.Enum
				}
				if param.Schema.Format != "" {
					query_props["format"] = param.Schema.Format
				}
				if param.Schema.Default != nil {
					query_props["default"] = param.Schema.Default
				}
				if param.Schema.Description != "" {
					query_props["description"] = param.Schema.Description
				}
				if param.Schema.Items != nil {
					query_props["items"] = param.Schema.Items
				}
				if param.Schema.Properties != nil {
					query_props["properties"] = param.Schema.Properties
				}
			} else if param.In == "path" {
				path_props[param.Name] = param
				path_props["type"] = param.Schema.Type
				if param.Schema.Enum != nil {
					path_props["enum"] = param.Schema.Enum
				}
				if param.Schema.Format != "" {
					path_props["format"] = param.Schema.Format
				}
				if param.Schema.Default != nil {
					path_props["default"] = param.Schema.Default
				}
				if param.Schema.Description != "" {
					path_props["description"] = param.Schema.Description
				}
				if param.Schema.Items != nil {
					path_props["items"] = param.Schema.Items
				}
			}
		}

		if len(query_props) > 0 {
			opts = append(opts, mcp.WithObject("searchParams", mcp.Description("url parameters for the tool"), mcp.Properties(query_props)))
		}
		if len(path_props) > 0 {
			opts = append(opts, mcp.WithObject("pathNames", mcp.Description("path parameters for the tool"), mcp.Properties(path_props)))
		}

		// Handle request body parameters if present
		props := map[string]interface{}{}
		if api.RequestBody != nil && len(api.RequestBody.Content) > 0 {
			for _, mediaType := range api.RequestBody.Content {
				if mediaType.Schema != nil {
					for propName, propSchema := range mediaType.Schema.Properties {
						props[propName] = propSchema
						props["type"] = propSchema.Type
						if propSchema.Enum != nil {
							props["enum"] = propSchema.Enum
						}
						if propSchema.Format != "" {
							props["format"] = propSchema.Format
						}
						if propSchema.Default != nil {
							props["default"] = propSchema.Default
						}
						if propSchema.Description != "" {
							props["description"] = propSchema.Description
						}
						if propSchema.Items != nil {
							props["items"] = propSchema.Items
						}
						if propSchema.Properties != nil {
							props["properties"] = propSchema.Properties
						}
					}
				}
			}
			opts = append(opts, mcp.WithObject("requestBody", mcp.Description("request body for the tool"), mcp.Properties(props)))
		}

		// Create the tool and handler
		tool := mcp.NewTool(finalName, opts...)

		// Properly construct the full URL with correct path handling
		fullURL := constructURL(baseURL, api.Path)

		// Merge extra headers and authentication information
		mergedHeaders := make(map[string]string)
		for k, v := range extraHeaders {
			mergedHeaders[k] = v
		}

		// Create appropriate handler based on authentication requirements
		var handler func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error)
		if requiresDynamicAuth && session != nil {
			// Use dynamic authentication handler with session and auth config, including parser support
			handler = NewToolHandlerWithSessionAndParser(api.Method, fullURL, mergedHeaders, session, authConfig, parser)
		} else {
			// Use static authentication handler (no session or auth config) with parser support
			handler = NewToolHandlerWithSessionAndParser(api.Method, fullURL, mergedHeaders, nil, nil, parser)
		}

		// Add the tool to the server
		s.AddTool(tool, handler)
	}

	// Save all mappings to the database
	saveErr := toolMappingManager.SaveMCPNames(finalToolID, newMappings)
	if saveErr != nil {
		log.Printf("[WARNING] Failed to save MCP name mappings: %v", saveErr)
	} else {
		log.Printf("[TOOL MAPPING] Successfully saved %d MCP name mappings for tool ID: %s", len(newMappings), finalToolID)
	}

	return s, nil
}

// parseAuthConfigFromExtension parses authentication configuration from x-mcp-auth extension
func parseAuthConfigFromExtension(extension interface{}) (*AuthConfig, error) {
	// Convert extension to map
	extensionMap, ok := extension.(map[string]interface{})
	if !ok {
		return nil, fmt.Errorf("x-mcp-auth extension must be an object")
	}

	// Create AuthConfig from extension data
	config := &AuthConfig{}

	if authType, ok := extensionMap["type"].(string); ok {
		config.Type = authType
	}

	if tokenPath, ok := extensionMap["token_path"].(string); ok {
		config.TokenPath = tokenPath
	}

	if tokenFormat, ok := extensionMap["token_format"].(string); ok {
		config.TokenFormat = tokenFormat
	}

	if headerName, ok := extensionMap["header_name"].(string); ok {
		config.HeaderName = headerName
	}

	if queryParam, ok := extensionMap["query_param"].(string); ok {
		config.QueryParam = queryParam
	}

	if tokenPrefix, ok := extensionMap["token_prefix"].(string); ok {
		config.TokenPrefix = tokenPrefix
	}

	if expiresPath, ok := extensionMap["expires_path"].(string); ok {
		config.ExpiresPath = expiresPath
	}

	if requires, ok := extensionMap["requires"].([]interface{}); ok {
		config.Requires = make([]string, len(requires))
		for i, req := range requires {
			if reqStr, ok := req.(string); ok {
				config.Requires[i] = reqStr
			}
		}
	}

	if metadata, ok := extensionMap["metadata"].(map[string]interface{}); ok {
		config.Metadata = make(map[string]string)
		for k, v := range metadata {
			if vStr, ok := v.(string); ok {
				config.Metadata[k] = vStr
			}
		}
	}

	// Validate the configuration
	if err := config.Validate(); err != nil {
		return nil, fmt.Errorf("invalid auth config: %w", err)
	}

	return config, nil
}

// generateEnhancedToolDescription creates an intelligent tool description with authentication information
func generateEnhancedToolDescription(api APIEndpoint, authConfig *AuthConfig) string {
	// Start with basic description
	description := ""
	
	// Add operation ID if available and meaningful
	if api.OperationID != "" && api.OperationID != strings.ToLower(api.Method) {
		description += api.OperationID
	}
	
	// Add summary if available
	if api.Summary != "" {
		if description != "" {
			description += " - "
		}
		description += api.Summary
	}
	
	// Add detailed description if available and different from summary
	if api.Description != "" && api.Description != api.Summary {
		if description != "" {
			description += ". "
		}
		description += api.Description
	}
	
	// Add intelligent authentication information with enhanced context
	if authConfig != nil {
		authInfo := generateIntelligentAuthDescription(authConfig, api)
		if authInfo != "" {
			if description != "" {
				description += ". "
			}
			description += authInfo
		}
	}
	
	// Ensure description is not empty
	if description == "" {
		description = fmt.Sprintf("%s %s", api.Method, api.Path)
	}
	
	return description
}

// generateAuthenticationDescription creates user-friendly authentication descriptions
func generateAuthenticationDescription(authConfig *AuthConfig) string {
	if authConfig == nil {
		return ""
	}
	
	switch authConfig.Type {
	case "login":
		return "🔐 Authentication endpoint - call this first to obtain access credentials for protected endpoints"
	case "logout":
		return "🚪 Logout endpoint - call this to invalidate current authentication session"
	case "refresh":
		return "🔄 Token refresh endpoint - call this to renew expired authentication tokens"
	default:
		// Handle endpoints that require authentication
		if len(authConfig.Requires) > 0 {
			if len(authConfig.Requires) == 1 {
				return fmt.Sprintf("🔒 Requires authentication (%s) - ensure you call the login endpoint first", authConfig.Requires[0])
			} else {
				return fmt.Sprintf("🔒 Requires authentication (%s) - ensure you call the login endpoint first", strings.Join(authConfig.Requires, ", "))
			}
		}
	}
	
	return ""
}

// generateIntelligentAuthDescription creates context-aware authentication descriptions for AI agents
func generateIntelligentAuthDescription(authConfig *AuthConfig, api APIEndpoint) string {
	if authConfig == nil {
		return ""
	}
	
	switch authConfig.Type {
	case "login":
		// Provide more specific guidance for login endpoints while maintaining backward compatibility
		authType := "session"
		if authConfig.Metadata != nil && authConfig.Metadata["auth_type"] != "" {
			authType = authConfig.Metadata["auth_type"]
		}
		
		tokenInfo := ""
		if authConfig.TokenPath != "" {
			tokenInfo = fmt.Sprintf(" Token will be extracted from response path: %s.", authConfig.TokenPath)
		}
		
		return fmt.Sprintf("🔐 Authentication endpoint - call this first to obtain %s credentials.%s This must be called before any protected endpoints.", authType, tokenInfo)
		
	case "logout":
		return "🚪 Logout endpoint - call this to invalidate current authentication session and clear tokens"
		
	case "refresh":
		return "🔄 Token refresh endpoint - call this to renew expired authentication tokens without re-authenticating"
		
	default:
		// Handle endpoints that require authentication with more intelligent descriptions
		if len(authConfig.Requires) > 0 {
			// Create more specific guidance based on the endpoint context
			actionContext := inferEndpointAction(api)
			
			if len(authConfig.Requires) == 1 {
				return fmt.Sprintf("🔒 Requires authentication (%s) - ensure you call the login endpoint first. %s", 
					authConfig.Requires[0], actionContext)
			} else {
				return fmt.Sprintf("🔒 Requires authentication (%s) - ensure you call the login endpoint first. %s", 
					strings.Join(authConfig.Requires, ", "), actionContext)
			}
		}
	}
	
	return ""
}

// inferEndpointAction provides context about what the endpoint does based on method and path
func inferEndpointAction(api APIEndpoint) string {
	method := strings.ToUpper(api.Method)
	path := strings.ToLower(api.Path)
	
	// Analyze the path to understand the action - check admin first as it's more specific
	if strings.Contains(path, "admin") {
		return "This is an administrative endpoint with elevated privileges."
	} else if strings.Contains(path, "user") {
		switch method {
		case "GET":
			return "This endpoint retrieves user information."
		case "POST":
			return "This endpoint creates or updates user data."
		case "PUT", "PATCH":
			return "This endpoint modifies user information."
		case "DELETE":
			return "This endpoint removes user data."
		}
	} else if strings.Contains(path, "data") || strings.Contains(path, "list") {
		switch method {
		case "GET":
			return "This endpoint retrieves protected data."
		case "POST":
			return "This endpoint creates new data entries."
		case "PUT", "PATCH":
			return "This endpoint modifies existing data."
		case "DELETE":
			return "This endpoint removes data entries."
		}
	}
	
	// Generic action descriptions based on HTTP method
	switch method {
	case "GET":
		return "This endpoint retrieves protected information."
	case "POST":
		return "This endpoint creates or submits protected data."
	case "PUT", "PATCH":
		return "This endpoint modifies protected resources."
	case "DELETE":
		return "This endpoint removes protected resources."
	default:
		return "This endpoint performs protected operations."
	}
}

// generateDependencyDescription creates intelligent dependency descriptions for authenticated endpoints
func generateDependencyDescription(allAPIs []APIEndpoint, requiredAuthTypes []string) string {
	if len(requiredAuthTypes) == 0 {
		return ""
	}
	
	// Find login endpoints that provide the required authentication types
	var loginEndpoints []LoginEndpointInfo
	
	for _, api := range allAPIs {
		if api.Extensions != nil {
			if authExtension, exists := api.Extensions["x-mcp-auth"]; exists {
				if authConfig, err := parseAuthConfigFromExtension(authExtension); err == nil {
					if authConfig.Type == "login" {
						// Check if this login endpoint provides any of the required auth types
						authType := "default" // Default auth type
						if authConfig.Metadata != nil && authConfig.Metadata["auth_type"] != "" {
							authType = authConfig.Metadata["auth_type"]
						}
						
						// Check if this login endpoint provides any required auth type
						for _, requiredType := range requiredAuthTypes {
							if authType == requiredType {
								loginInfo := LoginEndpointInfo{
									Name:     generateEndpointDisplayName(api),
									AuthType: authType,
									Path:     api.Path,
									Method:   api.Method,
								}
								loginEndpoints = append(loginEndpoints, loginInfo)
								break
							}
						}
					}
				}
			}
		}
	}
	
	// Generate intelligent dependency description
	if len(loginEndpoints) > 0 {
		if len(loginEndpoints) == 1 {
			login := loginEndpoints[0]
			return fmt.Sprintf("📋 AUTHENTICATION WORKFLOW: First call '%s' (%s %s) to obtain %s credentials, then use this endpoint.", 
				login.Name, login.Method, login.Path, login.AuthType)
		} else {
			var loginNames []string
			for _, login := range loginEndpoints {
				loginNames = append(loginNames, fmt.Sprintf("'%s' (%s %s)", login.Name, login.Method, login.Path))
			}
			return fmt.Sprintf("📋 AUTHENTICATION WORKFLOW: First call one of these login endpoints: %s, then use this endpoint.", 
				strings.Join(loginNames, ", "))
		}
	}
	
	// Provide more specific guidance when no login endpoints are found
	authTypeList := strings.Join(requiredAuthTypes, ", ")
	return fmt.Sprintf("📋 AUTHENTICATION REQUIRED: This endpoint requires %s authentication. Look for a login endpoint that provides these credentials and call it first.", authTypeList)
}

// LoginEndpointInfo contains information about a login endpoint
type LoginEndpointInfo struct {
	Name     string
	AuthType string
	Path     string
	Method   string
}

// generateEndpointDisplayName creates a user-friendly display name for an API endpoint
func generateEndpointDisplayName(api APIEndpoint) string {
	// Try to use operation ID if it's meaningful
	if api.OperationID != "" && api.OperationID != strings.ToLower(api.Method) {
		return api.OperationID
	}
	
	// Try to use summary if available
	if api.Summary != "" {
		return api.Summary
	}
	
	// Generate a name from method and path
	pathParts := strings.Split(strings.Trim(api.Path, "/"), "/")
	if len(pathParts) > 0 {
		lastPart := pathParts[len(pathParts)-1]
		// Remove path parameters
		lastPart = strings.ReplaceAll(lastPart, "{", "")
		lastPart = strings.ReplaceAll(lastPart, "}", "")
		if lastPart != "" {
			return fmt.Sprintf("%s %s", strings.ToUpper(api.Method), lastPart)
		}
	}
	
	// Fallback
	return fmt.Sprintf("%s %s", strings.ToUpper(api.Method), api.Path)
}

// generateToolID creates a consistent ID for a tool based on API info
func generateToolID(apiInfo APIInfo) string {
	// Create a unique identifier based on API title and other metadata
	// This ensures the same API spec always gets the same tool ID
	inputStr := fmt.Sprintf("%s_%s_%s", apiInfo.Title, apiInfo.Version, apiInfo.Description)

	// Generate UUID-like hash from the input string
	hash := md5.Sum([]byte(inputStr))
	hexHash := hex.EncodeToString(hash[:])

	// Format as UUID-like string for compatibility with existing systems
	uuid := fmt.Sprintf("%s-%s-%s-%s-%s",
		hexHash[0:8], hexHash[8:12], hexHash[12:16], hexHash[16:20], hexHash[20:32])

	return uuid
}

// getCommonAlternative 获取字段名的常见错误替代
func getCommonAlternative(fieldName string) string {
	alternatives := map[string]string{
		"name":     "username",
		"email":    "mail",
		"password": "pass",
	}
	
	if alt, exists := alternatives[fieldName]; exists {
		return alt
	}
	return "other_variations"
}

// validateParametersWithOpenAPI 验证参数是否符合OpenAPI规范
func validateParametersWithOpenAPI(toolName string, params map[string]interface{}) error {
	// 这里可以添加更复杂的验证逻辑
	// 目前先实现基本的参数结构检查
	
	// 检查是否有结构化参数
	hasStructuredParams := params["pathNames"] != nil || params["searchParams"] != nil || params["requestBody"] != nil
	
	if !hasStructuredParams {
		// 检查是否有常见的参数映射问题
		if hasCommonMappingIssues(params) {
			return fmt.Errorf("detected common parameter mapping issues")
		}
	}
	
	return nil
}

// hasCommonMappingIssues 检查是否有常见的参数映射问题
func hasCommonMappingIssues(params map[string]interface{}) bool {
	// 检查常见的错误映射
	commonIssues := map[string][]string{
		"username": {"name"},     // username应该是name
		"user":     {"name"},     // user应该是name
		"login":    {"name"},     // login应该是name
		"mail":     {"email"},    // mail应该是email
		"e_mail":   {"email"},    // e_mail应该是email
	}
	
	for wrongField, correctFields := range commonIssues {
		if _, hasWrong := params[wrongField]; hasWrong {
			for _, correctField := range correctFields {
				if _, hasCorrect := params[correctField]; !hasCorrect {
					log.Printf("[PARAMETER_VALIDATION] Detected mapping issue: found '%s' but expected '%s'", wrongField, correctField)
					return true
				}
			}
		}
	}
	
	return false
}
